/*
 * Test_Board.cpp
 *
 *  Created on: Apr 1, 2014
 *      Author: zby
 */
#include "Test_Board.h"

using namespace board;

CppUnit::Test* Test_Board::suite(){
    CppUnit::TestSuite* suiteOfTests = new CppUnit::TestSuite("Test_Board");
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Board>("test_def_constructor",&Test_Board::test_def_constructor));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Board>("test_def_constructor",&Test_Board::test_def_constructor_cpy));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Board>("test_def_constructor",&Test_Board::test_put_move));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Board>("test_def_constructor",&Test_Board::test_friend_op));

    return suiteOfTests;
}

void Test_Board::test_def_constructor(void){
    //check connection on corner
    pos_X x;
    pos_Y y;
    std::vector<graph::Node> neigh;

    x=0;    y=0;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(2==neigh.size() && 1==neigh[0] && 7==neigh[1]);
    x=0;    y=6;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(3==neigh.size() && 5==neigh[0] && 12==neigh[1] && 13==neigh[2]);
    x=6;    y=0;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(3==neigh.size() && 35==neigh[0] && 36==neigh[1] && 43==neigh[2]);
    x=6;    y=6;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(2==neigh.size() && 41==neigh[0] && 47==neigh[1]);

    //check edges
    x=0;    y=1;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(4==neigh.size() && 0==neigh[0] && 2==neigh[1] && 7==neigh[2] && 8==neigh[3]);
    //check if nodes are connected with init edge value
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[0]));
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[1]));
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[2]));
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[3]));
    x=0;    y=3;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(4==neigh.size() && 2==neigh[0] && 4==neigh[1] && 9==neigh[2] && 10==neigh[3]);
    x=0;    y=5;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(4==neigh.size() && 4==neigh[0] && 6==neigh[1] && 11==neigh[2] && 12==neigh[3]);
    x=1;    y=6;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(4==neigh.size() && 6==neigh[0] && 12==neigh[1] && 19==neigh[2] && 20==neigh[3]);
    x=5;    y=6;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(4==neigh.size() && 34==neigh[0] && 40==neigh[1] && 47==neigh[2] && 48==neigh[3]);
    x=5;    y=0;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(4==neigh.size() && 28==neigh[0] && 29==neigh[1] && 36==neigh[2] && 42==neigh[3]);
    x=6;    y=4;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(4==neigh.size() && 39==neigh[0] && 40==neigh[1] && 45==neigh[2] && 47==neigh[3]);

    //inside the board
    x=1;    y=5;
    neigh.clear();
    neigh = b1->Neighbors(static_cast<graph::NodeVal>(x*7+y));
    CPPUNIT_ASSERT(6==neigh.size() && 5==neigh[0] && 6==neigh[1] && 11==neigh[2] &&
            13==neigh[3] && 18==neigh[4] && 19==neigh[5]);
    //check if nodes are connected with init edge value
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[0]));
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[1]));
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[2]));
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[3]));
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[4]));
    CPPUNIT_ASSERT(Board::EdgeInit==b1->Get_edge_value(static_cast<graph::NodeVal>(x*7+y),neigh[5]));

    //test for grouped line West, East, North, South
    //WE
    CPPUNIT_ASSERT(0==b1->fau_WE.root(0) && 0==b1->fau_WE.root(7) && 0==b1->fau_WE.root(14) && 0==b1->fau_WE.root(21) &&
                   0==b1->fau_WE.root(28) && 0==b1->fau_WE.root(35) && 0==b1->fau_WE.root(42));
    CPPUNIT_ASSERT(48==b1->fau_WE.root(6) && 48==b1->fau_WE.root(13) && 48==b1->fau_WE.root(20) && 48==b1->fau_WE.root(27) &&
                   48==b1->fau_WE.root(34) && 48==b1->fau_WE.root(41) && 48==b1->fau_WE.root(48));
    //SE
    CPPUNIT_ASSERT(0==b1->fau_SN.root(0) && 0==b1->fau_SN.root(1) && 0==b1->fau_SN.root(2) && 0==b1->fau_SN.root(3) &&
                   0==b1->fau_SN.root(4) && 0==b1->fau_SN.root(5) && 0==b1->fau_SN.root(6));
    CPPUNIT_ASSERT(48==b1->fau_SN.root(42) && 48==b1->fau_SN.root(42) && 48==b1->fau_SN.root(42) && 48==b1->fau_SN.root(42) &&
                   48==b1->fau_SN.root(42) && 48==b1->fau_SN.root(42) && 48==b1->fau_SN.root(42));
    //others
    CPPUNIT_ASSERT(8==b1->fau_WE.root(8) && 12==b1->fau_WE.root(12) && 36==b1->fau_WE.root(36) && 40==b1->fau_WE.root(40));
    CPPUNIT_ASSERT(8==b1->fau_SN.root(8) && 12==b1->fau_SN.root(12) && 36==b1->fau_SN.root(36) && 40==b1->fau_SN.root(40));
}

void Test_Board::test_def_constructor_cpy(void)
{
    using graph::Node;

    //check connection on corner
    pos_X x;
    pos_Y y;

    x=0; y=0;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A));
    x=0; y=3;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A));
    x=3; y=0;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A));
    x=3; y=3;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A));
    x=3; y=1;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A));
    x=0; y=2;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_B));
    x=1; y=2;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_B));
    x=2; y=2;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_B));
    x=3; y=2;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_B));
    x=5; y=4;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A));
    x=5; y=5;
    b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A));

    b2=new Board(*b1);

    cout<<*b1<<endl;
    cout<<*b2<<endl;

    CPPUNIT_ASSERT(b1->GetBoardSize()==b2->GetBoardSize());
    CPPUNIT_ASSERT( 22==b2->fau_WE.root(0) && 22==b2->fau_WE.root(21) && 22==b2->fau_WE.root(42) &&
                    48==b2->fau_WE.root(6) && 48==b2->fau_WE.root(13) && 48==b2->fau_WE.root(48) );
    CPPUNIT_ASSERT( 23==b2->fau_SN.root(0) && 23==b2->fau_SN.root(6) && 23==b2->fau_SN.root(9) &&
                    48==b2->fau_SN.root(42) && 48==b2->fau_SN.root(46) && 48==b2->fau_SN.root(48) );
    CPPUNIT_ASSERT( 40==b2->fau_WE.root(39) && 40==b2->fau_WE.root(40) );
}

void Test_Board::test_put_move(void)
{
    using graph::Node;
    //check connection on corner
    pos_X x;
    pos_Y y;
    Node k;
    x=0; y=0; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(true==b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    CPPUNIT_ASSERT(PLAYER_A==b1->Get_node_value(k));

    x=6; y=6; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(true==b1->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    CPPUNIT_ASSERT(PLAYER_B==b1->Get_node_value(k));

    x=0; y=6; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(true==b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    CPPUNIT_ASSERT(PLAYER_A==b1->Get_node_value(k));

    x=6; y=0; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(true==b1->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    CPPUNIT_ASSERT(PLAYER_B==b1->Get_node_value(k));

    //check connection on edge
    x=1; y=6; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(true==b1->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    CPPUNIT_ASSERT(PLAYER_B==b1->Get_node_value(k));

    x=2; y=0; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(true==b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    CPPUNIT_ASSERT(PLAYER_A==b1->Get_node_value(k));

    //putting in not vacant places are forbid
    x=0; y=0; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(false==b1->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    CPPUNIT_ASSERT(PLAYER_A==b1->Get_node_value(k));

    x=0; y=0; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(false==b1->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    CPPUNIT_ASSERT(PLAYER_A==b1->Get_node_value(k));

    x=2; y=0; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(false==b1->put_move(x,y,static_cast<_eplayer>(NONE)));
    CPPUNIT_ASSERT(PLAYER_A==b1->Get_node_value(k));

    //putting move with NONE player shall shall be allowed
    x=2; y=4; k=static_cast<Node>(x*7+y);
    CPPUNIT_ASSERT(true==b1->put_move(x,y,static_cast<_eplayer>(NONE)));
    CPPUNIT_ASSERT(NONE==b1->Get_node_value(k));

    //checking grouping
    //crate two divisible groups
    //1. (1,0)->(1,1)->(1,2) - node root: (1,2) PLAYER_A
    //2. (1,6)->(1,5)->(1,4) - node root: (1,4) PLAYER_A
    x=1; y=0;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    x=1; y=1;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    x=1; y=2;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    x=1; y=6;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    x=1; y=5;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    x=1; y=4;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    CPPUNIT_ASSERT(9==b2->fau_WE.root(7) && 11==b2->fau_WE.root(13));
    // put move (1,3) - will be the root of previous both groups
    x=1; y=3;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_A)));
    CPPUNIT_ASSERT(10==b2->fau_WE.root(7) && 10==b2->fau_WE.root(13));

    //checking grouping
    //crate two divisible groups
    //1. (2,0)->(2,1)->(2,2) - node root: (2,2) PLAYER_B
    //2. (2,6)->(2,5)->(2,4) - node root: (2,4) PLAYER_B
    x=2; y=0;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    x=2; y=1;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    x=2; y=2;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    x=2; y=6;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    x=2; y=5;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    x=2; y=4;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    CPPUNIT_ASSERT(16==b2->fau_SN.root(14) && 18==b2->fau_SN.root(20));
    // put move (1,3) - will be the root of previous both groups
    x=2; y=3;
    CPPUNIT_ASSERT(true==b2->put_move(x,y,static_cast<_eplayer>(PLAYER_B)));
    CPPUNIT_ASSERT(17==b2->fau_SN.root(14) && 17==b2->fau_SN.root(20));
}
void Test_Board::test_friend_op(void)
{
    b1->put_move(static_cast<pos_X>(0),static_cast<pos_Y>(0),static_cast<_eplayer>(PLAYER_A));
    b1->put_move(static_cast<pos_X>(0),static_cast<pos_Y>(6),static_cast<_eplayer>(PLAYER_B));
    b1->put_move(static_cast<pos_X>(6),static_cast<pos_Y>(0),static_cast<_eplayer>(PLAYER_B));
    b1->put_move(static_cast<pos_X>(6),static_cast<pos_Y>(6),static_cast<_eplayer>(PLAYER_A));
    b1->put_move(static_cast<pos_X>(3),static_cast<pos_Y>(3),static_cast<_eplayer>(PLAYER_A));
    b1->put_move(static_cast<pos_X>(5),static_cast<pos_Y>(6),static_cast<_eplayer>(PLAYER_B));
    cout<<*b1<<endl;
}

